import serial
import binascii
import serial.tools.list_ports


def list_ports():
    port_names = []
    ports = serial.tools.list_ports.comports()
    for port, desc, hwid in ports:
        print(f"Port: {port}, Description: {desc}, HWID: {hwid}")
        port_names.append(port)

    return port_names


class CommService:
    def __init__(self, comm_port):
        self.comm_port = comm_port
        self.ser_comm = None

    def set_comm_port(self, comm_port):
        self.comm_port = comm_port

    def open_comm(self):
        try:
            self.ser_comm = serial.Serial(self.comm_port, 115200, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,
                                          stopbits=serial.STOPBITS_ONE, timeout=1, xonxoff=False, rtscts=False,
                                          dsrdtr=False)
        except:
            return None
        return self.ser_comm

    def close_comm(self):
        if self.is_opened:
            self.ser_comm.close()
            self.ser_comm = None

    def sendData(self,data):
        if self.is_opened:
            try:
                self.ser_comm.write(data)
            except serial.serialutil.SerialTimeoutException:
                msg = 'err'
                return False, msg
            return True, ''
        else:
            msg = 'err'
            return False, msg
    def send_comm(self, data):
        if self.is_opened:
            try:
                self.ser_comm.write(bytearray.fromhex(data.replace(' ', '')))
            except serial.serialutil.SerialTimeoutException:
                msg = 'err'
                return False, msg
            return True, ''
        else:
            msg = 'err'
            return False, msg

    def read_comm(self):
        if self.is_opened:
            if self.ser_comm.in_waiting > 0:
                try:
                    data = self.ser_comm.read()
                except:
                    return None
                #return binascii.hexlify(data).decode('ascii')
                return data

            return None
        else:
            return None

    def is_opened(self):
        return self.ser_comm is not None and self.ser_comm.is_open

